package top.dark.search.thread;

import java.util.concurrent.*;

/**
 * Author: Darkn
 * description:
 * Create Time: 2021/3/15 13:51
 */
public class ThreadTest {

    /**
     * 1）、继承 Thread
         System.out.println("main线程运行......start ....");
         Thread01 thread01 = new Thread01();
         thread01.start();
         System.out.println("main线程运行......end ....");
     * 2）、实现 Runnable 接口
         System.out.println("main线程运行......start ....");
         Runnable01 runnable01 = new Runnable01();
         new Thread(runnable01).start();
         System.out.println("main线程运行......end ....");
     * 3）、实现 Callable 接口 + FutureTask （可以拿到返回结果，可以处理异常）
         System.out.println("main线程运行......start ....");
         FutureTask<Integer> futureTask = new FutureTask(new Callable01());
         new Thread(futureTask).start();
         Integer integer = futureTask.get();
         System.out.println("main线程运行......end ...." + integer);
         阻塞等待整个线程执行完毕，获取返回结果
     * 4）、线程池
         private static final ExecutorService executorService = Executors.newFixedThreadPool(10);
         Runnable01 runnable01 = new Runnable01();
         executorService.submit(runnable01);
     *  内存有限，创建线程耗资源
     *  业务代码里面，以上三种启动线程的方式都不用。【将所有的多线程异步任务都交给线程池执行】
     *
     * 区别：
     *    1、2不能获取到返回值，3能获取返回值
     *    1、2、3不能控制资源
     *    4可以控制资源，性能稳定。
     *
     *  默认线程池源码
        public ThreadPoolExecutor(
           int corePoolSize,
           int maximumPoolSize,
           long keepAliveTime,
           TimeUnit unit,
           BlockingQueue<Runnable> workQueue,
                new LinkedBlockingQueue<>(10000) 默认容量是Integer的最大值，可能会导致内存不够将整个内存占满
           ThreadFactory threadFactory,
           RejectedExecutionHandler handler
                四种策略：
                    DiscardOldestPolicy，丢弃掉队列中最老的数据，队头
                    AbortPolicy，丢弃掉新来的数据，并抛出异常
                    DiscardPolicy，丢弃掉最新的数据，不会抛出异常
                    CallerRunsPolicy，直接调用传入进来的线程的run方法，不启用线程调用，同步调用
        )
     四种默认线程池
         Executors.newCachedThreadPool();
            核心线程数量为0，所有的线程都可以被回收
         Executors.newScheduledThreadPool(1);
            定时任务调度线程池，可以设置延迟时间进行定时执行
         Executors.newFixedThreadPool(190);
            定长线程池，核心线程数=最大线程数
         Executors.newSingleThreadExecutor();
            单线程线程池，所有的线程任务放在队列中，由一个线程按顺序执行队列中的任务

     cpu轮转，上下文时间片切换，频繁的创建销毁特别消耗性能，如果使用线程池可以维持一定数据量的线程
     能减少上下文的切换频繁的创建销毁，提高效率

     多个异步任务，任务之间由一定的顺序关系依赖 ——》 任务编排
     */

    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        Executors.newCachedThreadPool();
       /* System.out.println("main线程运行......start ....");
        Runnable01 runnable01 = new Runnable01();
        executorService.submit(runnable01);
        System.out.println("main线程运行......end ....");

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 200,
                10L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10000));
        Executors.newCachedThreadPool();
        Executors.newScheduledThreadPool(1);
        Executors.newFixedThreadPool(190);
        Executors.newSingleThreadExecutor();*/

        // 1、创建一个异步任务
       /* CompletableFuture.runAsync(()->{
            System.out.println("线程号：" + Thread.currentThread().getId());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
        },executorService);*/

       // handle方法
       /* CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            // 能够感知结果，不能感知异常
            System.out.println("线程号：" + Thread.currentThread().getName());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
            return a;
        }, executorService).whenComplete((t, u) -> {
            // 能够感知异常，但是不能修改返回结果
            System.out.println("当前线程为：" + Thread.currentThread().getName());
            System.out.println("完成的结果：" + t + "，异常为：" + u);
        }).exceptionally((excption) -> {
            System.out.println("异常信息为：" + excption);
            return 666;
        }).handle((t,u)->{
            // 能够感知结果还能感知异常，同时还能修改结果
            if (t != null) {
                return t * 2;
            } else if (u != null){
                return 1000;
            }
            return 1000;
        });
        Integer integer = future.get();
        System.out.println("结果值为：" + integer);*/

        // 线程串行话
       /* CompletableFuture.supplyAsync(() -> {
            // 能够感知结果，不能感知异常
            System.out.println("线程号：" + Thread.currentThread().getName());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
            return a;
        }, executorService).thenRun(() -> {
            System.out.println("执行任务2.。。。。。。");
        });*/
        /*CompletableFuture.supplyAsync(() -> {
            // 能够感知结果，不能感知异常
            System.out.println("线程号：" + Thread.currentThread().getName());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
            return a;
        }, executorService).thenAccept((t) -> {
            System.out.println("执行任务2.。。。。。。,结果为：" + t);
        });*/

        /*CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 能够感知结果，不能感知异常
            System.out.println("线程号：" + Thread.currentThread().getName());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
            return a;
        }, executorService).thenApply((t) -> {
            System.out.println("执行任务2.。。。。。。,结果为：" + t);
            return "hello res " + t;
        });
        String s = future.get();
        System.out.println("执行结果：" + s);*/
        CompletableFuture.supplyAsync(() -> {
            // 能够感知结果，不能感知异常
            System.out.println("线程号：" + Thread.currentThread().getName());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
            return a;
        }, executorService);
        CompletableFuture.supplyAsync(() -> {
            // 能够感知结果，不能感知异常
            System.out.println("线程号：" + Thread.currentThread().getName());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
            return a;
        }, executorService);
    }

    private static final ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static class Callable01 implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            System.out.println("线程号：" + Thread.currentThread().getId());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
            return a;
        }
    }

    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("线程号：" + Thread.currentThread().getId());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
        }
    }

    public static class Runnable01 implements Runnable{
        @Override
        public void run() {
            System.out.println("线程号：" + Thread.currentThread().getId());
            int a = 1000 / 10;
            System.out.println("线程运行结果：" + a);
        }
    }

}
